﻿using OpenCvSharp;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

namespace ImageProcess
{
    public static class ImageHelper
    {

        /// <summary>
        /// 转换点坐标,从原始图片中的点转换到目标图片中对应的点
        /// </summary>
        /// <param name="original">原始图片大小</param>
        /// <param name="target">目标图片大小</param>
        /// <param name="point">要转换的坐标点</param>
        /// <returns></returns>
        public static System.Drawing.Point ConvetPointCoord(System.Drawing.Size original, System.Drawing.Size target, System.Drawing.Point point)
        {
            // 计算比例因子
            float scaleX = (float)target.Width / original.Width;
            float scaleY = (float)target.Height / original.Height;

            // 将点的坐标从原始图像空间转换到目标图像空间
            int convertedPointX = (int)(point.X * scaleX);
            int convertedPointY = (int)(point.Y * scaleY);

            return new System.Drawing.Point(convertedPointX, convertedPointY);
        }

        /// <summary>
        /// 转换矩形坐标,从原始图片中的矩形坐标转换到目标图片中对应的矩形坐标
        /// </summary>
        /// <param name="original">原始图片大小</param>
        /// <param name="target">目标图片大小</param>
        /// <param name="rect">要转换的矩形</param>
        /// <returns></returns>
        public static System.Drawing.Rectangle ConvetRectangleCoord(System.Drawing.Size original, System.Drawing.Size target, System.Drawing.Rectangle rect)
        {
            // 计算比例因子
            float scaleX = (float)target.Width / original.Width;
            float scaleY = (float)target.Height / original.Height;


            // 将点的坐标从原始图像空间转换到目标图像空间
            int convertedPointX = (int)(rect.X * scaleX);
            int convertedPointY = (int)(rect.Y * scaleY);

            int convertedW = (int)(rect.Width * scaleX);
            int convertedH = (int)(rect.Height * scaleY);
            return new System.Drawing.Rectangle(convertedPointX, convertedPointY, convertedW, convertedH);
        }

        /// <summary>
        /// 图片转字节数组
        /// </summary>
        /// <param name="img"></param>
        /// <returns></returns>
        public static byte[]? ImageToByte(Image img)
        {
            byte[]? bt = null;
            if (img != null)
            {
                using MemoryStream mostream = new MemoryStream();
#pragma warning disable CA1416 // 验证平台兼容性
                using Bitmap bmp = new(img);
                bmp.Save(mostream, System.Drawing.Imaging.ImageFormat.Png);//将图像以指定的格式存入缓存内存流
#pragma warning restore CA1416 // 验证平台兼容性
                bt = new byte[mostream.Length];
                mostream.Position = 0;//设置留的初始位置
                mostream.Read(bt, 0, Convert.ToInt32(bt.Length));
            }
            return bt;
        }

        /// <summary>
        /// 字节数组转换成图片(Image)
        /// </summary>
        /// <param name="byteArray"></param>
        /// <returns></returns>
        public static Image? ByteToImage(byte[] byteArray)
        {
            Image? image = null;
            using (MemoryStream mf = new())
            {
                foreach (var b in byteArray)
                {
                    mf.WriteByte(b);
                }
#pragma warning disable CA1416 // 验证平台兼容性
                image = Image.FromStream(mf);
#pragma warning restore CA1416 // 验证平台兼容性
            }
            return image;
        }

        /// <summary>
        /// 缩略图
        /// </summary>
        /// <param name="originalImage"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public static System.Drawing.Image? Resize(System.Drawing.Bitmap originalImage, int width, int height, string mode = "W")
        {
            double towidth = width;
            double toheight = height;

            Mat source = OpenCvSharp.Extensions.BitmapConverter.ToMat(originalImage);
            Mat outMat = new();
            switch (mode)
            {
                case "W":   //指定宽，高按比例                    
                    toheight = source.Height * width / (double)source.Width;
                    Cv2.Resize(source, outMat, new OpenCvSharp.Size(towidth, toheight));
                    break;
                case "H":   //指定高，宽按比例
                    towidth = source.Width * height / (double)source.Height;
                    Cv2.Resize(source, outMat, new OpenCvSharp.Size(towidth, toheight));
                    break;
                default:
                    Cv2.Resize(source, outMat, new OpenCvSharp.Size(towidth, toheight));
                    break;
            }
            return OpenCvSharp.Extensions.BitmapConverter.ToBitmap(outMat);
        }

        /// <summary>
        /// 缩略图
        /// </summary>
        /// <param name="originalImage"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public static System.Drawing.Image? Resize(string originalImage, int width, int height, string mode = "W")
        {
            double towidth = width;
            double toheight = height;

            Mat source = new(originalImage, ImreadModes.Color);
            Mat outMat = new();
            switch (mode)
            {
                case "W":   //指定宽，高按比例                    
                    toheight = source.Height * width / (double)source.Width;
                    Cv2.Resize(source, outMat, new OpenCvSharp.Size(towidth, toheight));
                    break;
                case "H":   //指定高，宽按比例
                    towidth = source.Width * height / (double)source.Height;
                    Cv2.Resize(source, outMat, new OpenCvSharp.Size(towidth, toheight));
                    break;
                default:
                    Cv2.Resize(source, outMat, new OpenCvSharp.Size(towidth, toheight));
                    break;
            }
            return OpenCvSharp.Extensions.BitmapConverter.ToBitmap(outMat);
        }

        /// <summary>
        /// 裁剪
        /// </summary>
        /// <param name="originalImage"></param>
        /// <param name="rectangle"></param>
        /// <returns></returns>
        public static System.Drawing.Bitmap? Crop(System.Drawing.Bitmap originalImage, System.Drawing.Rectangle rectangle)
        {
            using Mat source = OpenCvSharp.Extensions.BitmapConverter.ToMat(originalImage);
            Rect roi = new(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
            using Mat outMat = new(source, roi);
            return OpenCvSharp.Extensions.BitmapConverter.ToBitmap(outMat);
        }

        public static byte[] CropToBytes(System.Drawing.Bitmap originalImage, System.Drawing.Rectangle rectangle)
        {
            Mat source = OpenCvSharp.Extensions.BitmapConverter.ToMat(originalImage);
            Rect roi = new(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
            Mat outMat = new(source, roi);
            using var img = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(outMat);
            if(img != null) 
            {
                return ImageToByte(img);
            }
            return [];
        }

        /// <summary>
        /// 裁剪
        /// </summary>
        /// <param name="originalImage"></param>
        /// <param name="rectangle"></param>
        /// <returns></returns>
        public static System.Drawing.Image? Crop(string originalImage, System.Drawing.Rectangle rectangle)
        {
            Mat source = new(originalImage, ImreadModes.Color);
            Rect roi = new(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
            Mat outMat = new(source, roi);
            return OpenCvSharp.Extensions.BitmapConverter.ToBitmap(outMat);
        }

        public static System.Drawing.Bitmap? CropToZoom(System.Drawing.Bitmap originalImage, System.Drawing.Rectangle rectangle, float scalingFactor = 2f)
        {
            using Mat srcImg = OpenCvSharp.Extensions.BitmapConverter.ToMat(originalImage);
            Rect roi = new(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
            using Mat croppedImg = new(srcImg, roi);
            using Mat outputImg = new();
            var scaledSize = new OpenCvSharp.Size((int)Math.Round(rectangle.Width * scalingFactor), (int)Math.Round(rectangle.Height * scalingFactor));
            Cv2.Resize(croppedImg, outputImg, scaledSize);
            return OpenCvSharp.Extensions.BitmapConverter.ToBitmap(outputImg);
        }

       
    }
}
